home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / dfue / elcheapofax / trace / rcs / trace.c,v < prev   
Text File  |  1995-03-09  |  8KB  |  369 lines

  1. head    1.2;
  2. access;
  3. symbols
  4.     OCT93:1.2;
  5. locks;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.2
  10. date    93.07.10.03.26.42;    author Rhialto;    state Exp;
  11. branches;
  12. next    1.1;
  13.  
  14. 1.1
  15. date    93.07.01.00.48.49;    author Rhialto;    state Exp;
  16. branches;
  17. next    ;
  18.  
  19.  
  20. desc
  21. @Trace activity of the serial.device. Usefull to spy on other
  22. fax programs.
  23. @
  24.  
  25.  
  26. 1.2
  27. log
  28. @Also trace SDCMD_SETPARAMS.
  29. @
  30. text
  31. @;/*
  32. dcc -proto trace.c -o trace
  33. quit
  34. */
  35.  
  36. /*
  37.  * Serial Port tracing utility. Uses one or two dirty tricks, but mostly
  38.  * plays by the book. There are style problems with AbortIO, though.
  39.  * Perhaps you'd best redirect output to some FAST disk.
  40.  *
  41.  * $Id: trace.c,v 1.1 1993/07/01 00:48:49 Rhialto Exp $
  42.  * $Log: trace.c,v $
  43.  * Revision 1.1  1993/07/01  00:48:49  Rhialto
  44.  * Initial revision
  45.  *
  46.  */
  47.  
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include <signal.h>
  52.  
  53. #include <exec/execbase.h>
  54. #include <exec/memory.h>
  55. #include <devices/serial.h>
  56. #include <clib/exec_protos.h>
  57. #include <clib/alib_protos.h>
  58. #include <clib/dos_protos.h>
  59.  
  60. extern struct ExecBase *SysBase;
  61.  
  62. struct MsgPort *ReplyPort;
  63. struct MsgPort *BeginIOPort;
  64. void (*OldBeginIO)(__A1 struct IOExtSer *ios, __A6 struct Device *dev);
  65. void (*OldAbortIO)(__A1 struct IOExtSer *ios, __A6 struct Device *dev);
  66. int Outstanding;
  67.  
  68. struct MyIO {
  69.     struct IOExtSer io;
  70.     struct IOExtSer *orig;
  71.     struct Task *SigTask;
  72. };
  73.  
  74. void
  75. logit(struct IOExtSer *ios)
  76. {
  77. #define BFSIZ 160
  78.     char buffer[BFSIZ];
  79.     char *p, *q;
  80.     int len;
  81.  
  82.     switch (ios->IOSer.io_Command) {
  83.     case CMD_WRITE:
  84.     q = "CMD_WRITE";
  85.     len = ios->IOSer.io_Length;
  86.     break;
  87.     case CMD_READ:
  88.     q = "CMD_READ ";
  89.     len = ios->IOSer.io_Actual;
  90.     if (ios->IOSer.io_Error) {
  91.         printf("CMD_READ : error %d\n", ios->IOSer.io_Error);
  92.         return;
  93.     }
  94.     break;
  95.     case SDCMD_QUERY:
  96.     printf("SDCMD_QUERY: %d\n", ios->IOSer.io_Actual);
  97.     return;
  98.     case SDCMD_SETPARAMS:
  99.     printf("SDCMD_SETPARAMS: CtlChar: %08lx, RBufLen: %d, Baud: %d,\n",
  100.         ios->io_CtlChar,
  101.         ios->io_RBufLen,
  102.         ios->io_Baud);
  103.     printf("\tTermArray: %08lx %08lx, ReadLen: %d, WriteLen: %d, StopBits: %d,\n", 
  104.         ios->io_TermArray.TermArray0,
  105.         ios->io_TermArray.TermArray1,
  106.         ios->io_ReadLen,
  107.         ios->io_WriteLen,
  108.         ios->io_StopBits);
  109.     printf("\tXDISABLED %d EOFMODE %d SHARED %d RAD_BOOGIE %d 7WIRE %d\n",
  110.         (ios->io_SerFlags & SERF_XDISABLED) != 0,
  111.         (ios->io_SerFlags & SERF_EOFMODE) != 0,
  112.         (ios->io_SerFlags & SERF_SHARED) != 0,
  113.         (ios->io_SerFlags & SERF_RAD_BOOGIE) != 0,
  114.         (ios->io_SerFlags & SERF_7WIRE) != 0);
  115.     printf("\tPARTY_ODD %d PARTY_ON %d MSPON %d MARK %d\n",
  116.         (ios->io_SerFlags & SERF_PARTY_ODD) != 0,
  117.         (ios->io_SerFlags & SERF_PARTY_ON) != 0,
  118.         (ios->io_ExtFlags & SEXTF_MSPON) != 0,
  119.         (ios->io_ExtFlags & SEXTF_MARK) != 0);
  120.     return;
  121.     default:
  122.     printf("CMD_%d\n", ios->IOSer.io_Command);
  123.     return;
  124.     }
  125.     sprintf(buffer, "%s %3d: ", q, len);
  126.     p = buffer + strlen(buffer);
  127.     q = ios->IOSer.io_Data;
  128.  
  129.     while (len-- > 0 && p < &buffer[BFSIZ-5]) {
  130.     unsigned char c;
  131.  
  132.     c = *q++;
  133.     if (c & 0x80) {
  134.         *p++ = '~';
  135.         c &= 0x7F;
  136.     }
  137.     if (c < 0x20 || c == 0x7F) {
  138.         *p++ = '^';
  139.         c ^= 0x40;
  140.     }
  141.     *p++ = c;
  142.     }
  143.     *p++ = '\n';
  144.     *p     = '\0';
  145.     fputs(buffer,stdout);
  146. }
  147.  
  148. /*
  149.  * Here is where the I/O starts. We trace in the following way:
  150.  *
  151.  * CMD_WRITE: trace immediately, by putting it on the main process
  152.  *          port. It will be OldBeginIO()ed after tracing.
  153.  *
  154.  * CMD_READ: wait with trace until we know what we read. Patch up the
  155.  *         ProcPort so that WE will get it back when complete.
  156.  *         The main process will ReplyMsg() it after tracing.
  157.  */
  158.  
  159. __geta4
  160. void
  161. MyBeginIO(__A1 struct IOExtSer *ios, __A6 struct Device *dev)
  162. {
  163.     switch (ios->IOSer.io_Command) {
  164.     case CMD_READ:
  165.     case SDCMD_QUERY:
  166.     {
  167.         struct MyIO *myio;
  168.         int quick;
  169.  
  170.         quick = ios->IOSer.io_Flags & IOF_QUICK;
  171.         myio = AllocMem(sizeof(*myio), MEMF_ANY);
  172.         if (myio == NULL) {
  173.         /* Sorry, no memory to trace this one */
  174.         goto untraced;
  175.         }
  176.         myio->io = *ios;
  177.         myio->io.IOSer.io_Flags &= ~IOF_QUICK;
  178.         myio->io.IOSer.io_Message.mn_ReplyPort = ReplyPort;
  179.         myio->orig = ios;
  180.         ios->IOSer.io_Message.mn_Node.ln_Succ = (void *)myio;
  181.         ios->IOSer.io_Message.mn_Node.ln_Type = NT_FREEMSG;
  182.         myio->SigTask = FindTask(NULL);
  183.         Outstanding++;
  184.         (*OldBeginIO)(&myio->io, dev);
  185.         if (quick || ios->IOSer.io_Message.mn_ReplyPort == NULL) {
  186.         /* Argh! It seems that many programs (well, at least
  187.          * VLT) take liberties with setting the ReplyPort when
  188.          * they're doing a QUERY, or a quick READ. Admittedly,
  189.          * quick I/O is guaranteed, under limited circumstances,
  190.          * but that's no reason not to have a reply port...
  191.          * Anyway, we'll have to Wait() here, wether he likes
  192.          * it or not...
  193.          */
  194.         Wait(1);
  195.         }
  196.     }
  197.     break;
  198.     case CMD_WRITE:
  199.     case SDCMD_SETPARAMS:
  200.     ios->IOSer.io_Flags &= ~IOF_QUICK;
  201.     PutMsg(BeginIOPort, &ios->IOSer.io_Message);
  202.     break;
  203.     default:
  204.     untraced:
  205.     (*OldBeginIO)(ios, dev);
  206.     }
  207. }
  208.  
  209. /*
  210.  * Grmpf. This is ugly. The NT_FREEMSG means that it is safe to
  211.  * assume the ln_Succ points to our copied request. Forbid() is
  212.  * needed to make sure it won't get invalid before we us it.
  213.  */
  214.  
  215. __geta4
  216. void
  217. MyAbortIO(__A1 struct IOExtSer *ios, __A6 struct Device *dev)
  218. {
  219.     Forbid();
  220.     if (ios->IOSer.io_Message.mn_Node.ln_Type == NT_FREEMSG) {
  221.     (*OldAbortIO)((void *)ios->IOSer.io_Message.mn_Node.ln_Succ, dev);
  222.     Permit();
  223.     } else {
  224.     Permit();
  225.     (*OldAbortIO)(ios, dev);
  226.     }
  227. }
  228. void
  229. HandlePorts(void)
  230. {
  231.     struct IOExtSer *ios;
  232.  
  233.     while (ios = GetMsg(ReplyPort)) {
  234.     struct MyIO *myio;
  235.  
  236.     /* Prevent AbortIO() of my copied request */
  237.     ios->IOSer.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  238.  
  239.     if (Outstanding > 1 || Outstanding < 0) {
  240.         printf("[%d] ", Outstanding);
  241.     }
  242.     logit(ios);
  243.     Outstanding--;
  244.     myio = ios;
  245.     ios = myio->orig;
  246.     ios->IOSer.io_Error  = myio->io.IOSer.io_Error;
  247.     ios->IOSer.io_Actual = myio->io.IOSer.io_Actual;
  248.     ios->io_Status         = myio->io.io_Status;
  249.  
  250.     if (!(ios->IOSer.io_Flags & IOF_QUICK) &&
  251.         ios->IOSer.io_Message.mn_ReplyPort) {
  252.         ReplyMsg(&ios->IOSer.io_Message);
  253.     } else {
  254.         Signal(myio->SigTask, 1);
  255.     }
  256.     FreeMem(myio, sizeof(*myio));
  257.      }
  258.  
  259.     while (ios = GetMsg(BeginIOPort)) {
  260.     logit(ios);
  261.     (*OldBeginIO)(ios, ios->IOSer.io_Device);
  262.     }
  263. }
  264.  
  265. int
  266. main(int argc, char **argv)
  267. {
  268.     char *serialname;
  269.     int unit;
  270.     struct IOExtSer *ios;
  271.     struct Device *dev;
  272.     int running;
  273.     long waitmask;
  274.  
  275.     if (argc < 3) {
  276.     printf("Usage: [run] trace serial.device 0\n");
  277.     exit(10);
  278.     }
  279.  
  280.     serialname = argv[1];
  281.     unit = atoi(argv[2]);
  282.  
  283.     printf("Tracing %s %d\n", serialname, unit);
  284.  
  285.     ReplyPort = CreatePort("trace ReplyPort", -1);
  286.     if (ReplyPort == NULL)
  287.     goto exit;
  288.     BeginIOPort = CreatePort("trace BeginIOPort", -1);
  289.     if (BeginIOPort == NULL)
  290.     goto exit;
  291.     ios = (struct IOExtSer *)CreateExtIO(ReplyPort, sizeof(*ios));
  292.     if (ios == NULL)
  293.     goto exit;
  294.  
  295.     if (OpenDevice(serialname, unit, (struct IORequest *)ios, 0)) {
  296.     Forbid();
  297.     dev = FindName(&SysBase->DeviceList, serialname);
  298.     Permit();
  299.     if (dev == NULL) {
  300.         printf("Can't find %s...\n", serialname);
  301.         goto exit;
  302.     }
  303.     } else {
  304.     dev = ios->IOSer.io_Device;
  305.     CloseDevice((struct IORequest *)ios);
  306.     }
  307.  
  308.     signal(SIGINT, SIG_IGN);
  309.  
  310.     OldBeginIO = SetFunction(dev, DEV_BEGINIO, MyBeginIO);
  311.     OldAbortIO = SetFunction(dev, DEV_ABORTIO, MyAbortIO);
  312.     running = 1;
  313.  
  314.     waitmask = SIGBREAKF_CTRL_F | 1L << ReplyPort->mp_SigBit
  315.                 | 1L << BeginIOPort->mp_SigBit;
  316.     while (running || Outstanding > 0) {
  317.     long mask;
  318.  
  319.     mask = Wait(waitmask);
  320.  
  321.     HandlePorts();
  322.  
  323.     if (mask & SIGBREAKF_CTRL_F) {
  324.         SetFunction(dev, DEV_BEGINIO, OldBeginIO);
  325.         running = 0;
  326.     }
  327.     }
  328.  
  329.     SetFunction(dev, DEV_BEGINIO, OldBeginIO);
  330.     Delay(10);
  331.     SetFunction(dev, DEV_ABORTIO, OldAbortIO);
  332.     HandlePorts();
  333.     Delay(10);
  334.     HandlePorts();
  335.  
  336.     printf("Done tracing %s %d\n", serialname, unit);
  337.  
  338. exit:
  339.     if (ios)
  340.     DeleteExtIO((struct IORequest *)ios);
  341.     if (ReplyPort)
  342.     DeletePort(ReplyPort);
  343.     if (BeginIOPort)
  344.     DeletePort(BeginIOPort);
  345.  
  346.     return 0;
  347. }
  348. @
  349.  
  350.  
  351. 1.1
  352. log
  353. @Initial revision
  354. @
  355. text
  356. @d11 5
  357. a15 2
  358.  * $Id$
  359.  * $Log$
  360. d21 1
  361. d60 4
  362. d68 23
  363. d169 1
  364. d181 1
  365. a181 1
  366.  * assume the ln_Succ points to our copied request. Forbod() is
  367. d277 2
  368. @
  369.